package ffte.evaluate.vectors

import scala.math._
import breeze.math._
import scala.util.Random._
import ffte.algorithm.FFTMisc

/**
 * Direct Vector Generator for FFT Testing
 *
 * Generates test vectors using direct computation methods with precise mathematical
 * reference implementations. This class provides comprehensive test vector generation
 * including random inputs, unit impulse responses, and imaginary impulse responses
 * for validating FFT hardware implementations.
 *
 * Features:
 * - Random complex input generation with uniform distribution
 * - Unit impulse and imaginary impulse test vectors
 * - Support for both forward and inverse FFT transforms
 * - Configurable scaling for fixed-point arithmetic validation
 * - Mathematical reference implementation using double-precision arithmetic
 *
 * @param N FFT size (number of points)
 * @param S Scaling shift value for fixed-point representation
 * @param inv Inverse FFT flag (true for inverse FFT, false for forward FFT)
 *
 * @example
 * // Generate test vectors for 64-point forward FFT
 * val generator = DirectVector(64, 3, inv = false)
 * val testVector = generator.TV(10) // 10-bit input width
 *
 * // Generate unit impulse response
 * val impulse = generator.NV(0, 10) // DC impulse
 *
 * @see [[ffte.evaluate.vectors.genVector]] for the base trait interface
 * @see [[ffte.algorithm.FFTMisc]] for FFT mathematical implementations
 */
case class DirectVector(N:Int,S:Int,inv:Boolean=false) extends genVector {

    /**
     * Generates random test vectors with comprehensive coverage.
     *
     * Creates random complex input vectors and computes the corresponding
     * FFT output using reference double-precision implementation. The input
     * values are uniformly distributed in the range [-0.5, 0.5] for both
     * real and imaginary components.
     *
     * @param sx Input bit width for fixed-point scaling
     * @return TestVectors containing input data and expected output
     *
     * @note Input scaling differs from output scaling by S bits to account
     *       for FFT growth and normalization requirements
     */
    def TV(sx:Int) = {
        val x = new Array[Complex](N)
        for (i <- 0 until N) {
            x(i) = Complex(nextDouble()-0.5,nextDouble()-0.5)
        }
        val y = if(inv) FFTMisc.idft(x) else FFTMisc.dft(x)
        TestVectors(TestVectors.fromVC(x,sx),TestVectors.fromVC(y,sx-S))
    }

    /**
     * Generates Normalized Vector (unit impulse response) test vectors.
     *
     * Creates test vectors with a single non-zero impulse at position k
     * in the frequency domain, then computes the corresponding time-domain
     * response. This is particularly useful for validating the frequency
     * response characteristics and impulse response behavior of FFT implementations.
     *
     * @param k Impulse position index (0 ≤ k < N)
     * @param s Output scaling bit width
     * @return TestVectors containing impulse response input and expected output
     *
     * @note The impulse amplitude is 1/128 to prevent overflow in fixed-point
     * @note Different scaling for input (s) vs output (s-S) accounts for FFT growth
     */
    def NV(k:Int,s:Int) = {
        val y = new Array[Complex](N)
        for (i <- 0 until N) {
            y(i) = Complex(0.0,0.0)
        }
        y(k) = Complex(1.0/128.0,0.0)
        val x = if(inv) FFTMisc.dft(y) else FFTMisc.idft(y)

        TestVectors(TestVectors.fromVC(x,s),TestVectors.fromVC(y,s-S))
    }

    /**
     * Generates Imaginary Vector test vectors.
     *
     * Creates test vectors with a single pure imaginary impulse at position k
     * in the frequency domain, then computes the corresponding time-domain
     * response. This is useful for testing the imaginary component processing
     * and validating complex arithmetic operations in FFT implementations.
     *
     * @param k Imaginary impulse position index (0 ≤ k < N)
     * @param s Output scaling bit width
     * @return TestVectors containing imaginary impulse response input and expected output
     *
     * @note The imaginary impulse amplitude is 1/128 to prevent overflow
     * @note Pure imaginary inputs test complex conjugate symmetry properties
     */
    def IV(k:Int,s:Int) = {
        val y = new Array[Complex](N)
        for (i <- 0 until N) {
            y(i) = Complex(0.0,0.0)
        }
        y(k) = Complex(0.0,1.0/128.0)
        val x = if(inv) FFTMisc.dft(y) else FFTMisc.idft(y)

        TestVectors(TestVectors.fromVC(x,s),TestVectors.fromVC(y,s-S))
    }
}
